package cn.org.processor.guestbook.api.service.impl;

import cn.org.processor.guestbook.api.mapper.UserMapper;
import cn.org.processor.guestbook.api.mapper.UserProfileMapper;
import cn.org.processor.guestbook.api.mapper.WalletMapper;
import cn.org.processor.guestbook.api.model.request.UserChangePasswordRequest;
import cn.org.processor.guestbook.api.model.request.UserLoginRequest;
import cn.org.processor.guestbook.api.model.request.UserRegisterRequest;
import cn.org.processor.guestbook.api.service.UserService;
import cn.org.processor.guestbook.api.util.ContextHolderUtil;
import cn.org.processor.guestbook.api.util.IpUtil;
import cn.org.processor.guestbook.api.util.ReCaptchaUtil;
import cn.org.processor.guestbook.api.util.UserUtil;
import entity.User;
import io.Response;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import util.EncryptUtil;

import java.util.Objects;

@Service
@Slf4j
public class UserServiceImpl implements UserService {
    private final UserMapper userMapper;
    private final UserProfileMapper userProfileMapper;
    private final WalletMapper walletMapper;
    private final UserUtil userUtil;
    private final ReCaptchaUtil reCaptchaUtil;

    public UserServiceImpl(UserMapper userMapper, UserProfileMapper userProfileMapper, WalletMapper walletMapper,
                           UserUtil userUtil, ReCaptchaUtil reCaptchaUtil) {
        this.userMapper = userMapper;
        this.userProfileMapper = userProfileMapper;
        this.walletMapper = walletMapper;
        this.userUtil = userUtil;
        this.reCaptchaUtil = reCaptchaUtil;
    }

    @Override
    public Response login(UserLoginRequest request) {
        // 测试类可绕过验证码
        if (request.getCaptcha() != null && reCaptchaUtil.hasSecret()) {
            boolean verify = reCaptchaUtil.verify(request.getCaptcha(),
                    IpUtil.getIpAddr(ContextHolderUtil.getRequest()));
            if (!verify) {
                return Response.builder().ret(Response.Ret.FAILURE).msg("验证失败").build();
            }
        }

        User user = userMapper.findByUsername(request.getUsername());
        if (user == null ||
                !Objects.equals(user.getPassword(), EncryptUtil.getPasswordEncryptStr(request.getPassword()))) {
            return Response.builder().ret(Response.Ret.FAILURE).msg("用户名或密码错误").build();
        }


        return Response.builder()
                .ret(Response.Ret.SUCCESS)
                .msg("登录成功")
                .data(userUtil.getAccessToken(user))
                .build();
    }

    @Override
    @Transactional
    public Response register(UserRegisterRequest request) {
        // 测试类可绕过验证码
        if (request.getCaptcha() != null && reCaptchaUtil.hasSecret()) {
            boolean verify = reCaptchaUtil.verify(request.getCaptcha(),
                    IpUtil.getIpAddr(ContextHolderUtil.getRequest()));
            if (!verify) {
                return Response.builder().ret(Response.Ret.FAILURE).msg("验证失败").build();
            }
        }

        if (!Objects.equals(request.getPassword(), request.getConfirmPassword())) {
            return Response.builder().ret(Response.Ret.FAILURE).msg("两次输入的密码不一致").build();
        }

        Response resp = EncryptUtil.checkStrength(request.getPassword());
        if (!resp.isSuccess()) {
            return resp;
        }

        User user = userMapper.findByUsername(request.getUsername());
        if (user != null) {
            return Response.builder().ret(Response.Ret.FAILURE).msg("用户名已被占用").build();
        }

        user = new User();
        user.setUsername(request.getUsername());
        user.setPassword(EncryptUtil.getPasswordEncryptStr(request.getPassword()));
        user.setRole(request.getRole());
        user.setStatus(User.Status.NORMAL);

        int result = userMapper.create(user);
        if (result == 0) {
            log.error("Failed to create user: {}", user);

            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Response.builder().ret(Response.Ret.FAILURE).msg("注册失败").build();
        }

        result = userProfileMapper.createById(user.getId());
        if (result == 0) {
            log.error("Failed to create user profile: {}", user);

            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Response.builder().ret(Response.Ret.FAILURE).msg("注册失败").build();
        }

        result = walletMapper.createById(user.getId());
        if (result == 0) {
            log.error("Failed to create user wallet: {}", user);

            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return Response.builder().ret(Response.Ret.FAILURE).msg("注册失败").build();
        }

        return Response.builder().ret(Response.Ret.SUCCESS).msg("注册成功").build();
    }

    @Override
    public Response changePassword(UserChangePasswordRequest request) {
        if (!Objects.equals(request.getNewPassword(), request.getConfirmPassword())) {
            return Response.builder().ret(Response.Ret.FAILURE).msg("两次输入的密码不一致").build();
        }

        Response resp = EncryptUtil.checkStrength(request.getNewPassword());
        if (!resp.isSuccess()) {
            return resp;
        }

        User user = (User) ContextHolderUtil.getCurrentUser();
        if (!Objects.equals(user.getPassword(), EncryptUtil.getPasswordEncryptStr(request.getOldPassword()))) {
            return Response.builder().ret(Response.Ret.FAILURE).msg("旧密码错误").build();
        }

        user.setPassword(EncryptUtil.getPasswordEncryptStr(request.getNewPassword()));
        if (userMapper.updatePassword(user) > 0) {
            return Response.builder()
                    .ret(Response.Ret.SUCCESS).
                    msg("修改成功")
                    .data(userUtil.getAccessToken(user))
                    .build();
        }

        log.error("Failed to change password: {}", user);
        return Response.builder().ret(Response.Ret.FAILURE).msg("修改失败").build();
    }

    @Override
    public Response getMeta() {
        User user = (User) ContextHolderUtil.getCurrentUser();

        user.setPassword(null);
        return Response.builder().ret(Response.Ret.SUCCESS).msg("获取成功").data(user).build();
    }
}
